package com.xz.xzutils.module.xzmybatislogplus.socket;

import com.xz.xzutils.components.console.SqlConsole;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 *
 * NIO 服务端 暂时不用
 *
 * @author DONG.WANG17@HAND-CHINA.COM
 * @since 2025-02-14 21:04
 */
public class NIOServer {
    // 监听端口 TODO 配置获取
    private static final int PORT = 9090;
    // 缓冲区大小
    private static final int BUFFER_SIZE = 1024;

    // 私有构造函数，防止外部实例化。
    private NIOServer() {
    }

    public static void start(SqlConsole console) {
        // 1. 创建 Selector 和 ServerSocketChannel
        try (
                Selector selector = Selector.open();
                ServerSocketChannel serverChannel = ServerSocketChannel.open();
        ) {

            serverChannel.bind(new InetSocketAddress(PORT));
            serverChannel.configureBlocking(false);
            serverChannel.register(selector, SelectionKey.OP_ACCEPT);

            console.logInfoLn("NIO 服务端已启动，监听端口：" + PORT);

            // 2. 事件循环
            while (true) {
                selector.select(); // 阻塞等待就绪事件
                Set<SelectionKey> keys = selector.selectedKeys();
                Iterator<SelectionKey> iter = keys.iterator();
                while (iter.hasNext()) {
                    SelectionKey key = iter.next();
                    iter.remove();

                    try {
                        if (key.isAcceptable()) {
                            handleAccept(key, selector, console);
                        } else if (key.isReadable()) {
                            handleRead(key, console);
                        }
                    } catch (IOException e) {
                        key.cancel();
                        key.channel().close();
                    }
                }
            }
        } catch (Exception e) {
            console.error("服务器异常: " + e.getMessage());
        }
    }

    public static void stop() {
    }

    // 处理新连接
    private static void handleAccept(SelectionKey key, Selector selector, SqlConsole sqlConsole) throws IOException {
        ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
        SocketChannel clientChannel = serverChannel.accept();
        clientChannel.configureBlocking(false);
        clientChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(BUFFER_SIZE));
        sqlConsole.logInfoLn("客户端连接: " + clientChannel.getRemoteAddress());
    }

    // 处理数据读取
    private static void handleRead(SelectionKey key, SqlConsole console) throws IOException {
        SocketChannel channel = (SocketChannel) key.channel();
        ByteBuffer buffer = (ByteBuffer) key.attachment();

        int bytesRead = channel.read(buffer);
        if (bytesRead == -1) { // 客户端关闭连接
            console.logDebugLn("客户端断开: " + channel.getRemoteAddress());
            channel.close();
            return;
        }

        buffer.flip(); // 切换为读模式
        byte[] data = new byte[buffer.remaining()];
        buffer.get(data);
        String message = new String(data);
        console.logInfoLn(message);
        buffer.clear(); // 清空缓冲区复用
    }
}
